package web;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import model.Accion;
import model.Hecho;
import model.Precio;
import model.Regla;
import motor.IterativoReglas;

import service.ServiceProvider;

//Clase para registrar los hechos y luego invocar al Motor de Inferencia

public class MotorServlet extends HttpServlet {
	
	private static final long serialVersionUID = 1L;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		List<Accion> acciones = ServiceProvider.getDao().getAcciones();
		
		ServiceProvider.getDao().borrarHechos();
		List<Regla> reglas = ServiceProvider.getDao().getReglas();
		List<String> resultados = new ArrayList<String>();
		
		Map<String, String> subas = new HashMap<String, String>();
		Map<String, String> bajas = new HashMap<String, String>();		
		
		ArrayList<String> hechos = new ArrayList<String>();
		
		for (Accion a : acciones){
			List<Precio> precios = a.getPrecios();
			Collections.sort(precios, new Comparator<Precio>() {

				@Override
				public int compare(Precio o1, Precio o2) {
					return o1.getFecha().compareTo(o2.getFecha());
				}
			});
			
			if (precios.size() >= 5){
				Precio p0 = precios.get(precios.size() - 5);
				Precio pf = precios.get(precios.size() - 1);
				BigDecimal cien = new BigDecimal("100");
				BigDecimal diez = BigDecimal.TEN;
				BigDecimal cincuenta = new BigDecimal("50");
				
				BigDecimal delta = pf.getValor().subtract(p0.getValor()).divide(pf.getValor(), BigDecimal.ROUND_HALF_EVEN).multiply(cien);
				
				if (delta.abs().compareTo(diez) == 1 && delta.abs().compareTo(cincuenta) == -1){
					if (delta.signum() == -1){
						// Bajo el porcentaje adecuado
						bajas.put(a.getRic(), a.getRic() + " bajó más de 10% (" + delta.toString() + "% )");
						String h = "[PRECIO] de " + a.getRic() + " [BAJA] [10%]";
						hechos.add(h);
						ServiceProvider.getDao().saveHecho(h);
					}
					if (delta.signum() == 1){
						// Subio el porcentaje adecuado
						subas.put(a.getRic(), a.getRic() + " subió más de 10% (" + delta.toString() + "% )");
						String h = "[PRECIO] de " + a.getRic() + " [SUBE] [10%]";
						hechos.add(h);
						ServiceProvider.getDao().saveHecho(h);
					}
				}
			}			
		}
		
		Set<String> hechosParaEvaluar = new HashSet<String>();
		hechosParaEvaluar.addAll(subas.keySet());
		hechosParaEvaluar.addAll(bajas.keySet());
				
		for (String s : hechosParaEvaluar){
			for (Regla r : reglas){
				if (r.cons.contains("#X#")){
					Regla resuelta = new Regla();
					resuelta.ant = r.ant.replace("#X#", s);
					if (r.ant1 != null){
						resuelta.ant1 = r.ant1.replace("#X#", s);
					}
					resuelta.cons = r.cons.replace("#X#", s);
					resuelta.union = r.union;
					
	                 String reglaString = new String();
	                 
	                 if(resuelta.ant!=null){ 
	                	 reglaString+=resuelta.ant;
	                 }
	                 if(resuelta.ant1!=null){ 
	                	 reglaString+="&"+resuelta.ant1;
	                 }	                  
	                 if(resuelta.cons!=null){
	                     reglaString+="=>"+resuelta.cons;
	                 }
	                 
	                 ArrayList<String> reglasResueltas = new ArrayList<String>();
	                 reglasResueltas.add(reglaString);
	                 
	                 try {
						IterativoReglas motor = new IterativoReglas(resuelta.cons, reglasResueltas, hechos);
						String result = motor.execute();
						if (result.contains("YES")){
							resultados.add("Regla " + reglaString + ": " + result);
						}	
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
	                 
				}				
			}
		}
	
        PrintWriter out = resp.getWriter();		
        out.println("<HEAD><TITLE>Motor de Inferencia</TITLE></HEAD><BODY>");
        out.println("<a href=\"/tpfinal\">Menu</a>");
        
        /*
        out.println("HECHOS DETECTADOS");
        out.println("<table>");
        out.println("<tr><td>###SUBAS###</td></tr>");
        for (String s : subas.keySet()){
        	out.println("<tr>");        	
            out.println("<td>" + subas.get(s) + "</td>");
        }
        out.println("</table>");             
        out.println("<table>");
        out.println("<tr><td>###BAJAS###</td></tr>");
        
        for (String b : bajas.keySet()){
        	out.println("<tr>");        	
            out.println("<td>" + bajas.get(b) + "</td>");        	
        }
        out.println("</table>");
        */
        out.println("<table>");
        out.println("<tr><td>###RESULTADOS###</td></tr>");
        for (String r : resultados){
        	out.println("<tr>");        	
            out.println("<td>" + r + "</td>");
        }
        out.println("<tr><td>################</td></tr>");
        out.println("</table>");
        out.println("<form action=\"MotorServlet\" method=\"POST\"><input type=\"Submit\" value=\"Ver Hechos\"></form>");			
        out.println("</BODY>");
        out.close();	
        
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
        PrintWriter out = resp.getWriter();		
        out.println("<HEAD><TITLE>Motor de Inferencia - Hechos Generados</TITLE></HEAD><BODY>");
        out.println("<a href=\"/tpfinal\">Menu</a>");
        out.println("<table>");
        out.println("<tr><td>###HECHOS###</td></tr>");
        List<Hecho> hechos = ServiceProvider.getDao().getHechos();
        for (Hecho h : hechos){
        	out.println("<tr>");        	
            out.println("<td>" + h.descripcion + "</td>");
        }
        out.println("</table>");        
        out.println("</BODY>");        
	}
}
